import 'dart:math';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'dart:ui';
import 'dart:async'; 
import 'package:flutter/material.dart';
import '../pages/mock.dart';
import '../pages/color_config.dart';

/// 设备状态管理提供者
class OpenCVProvider {
  late Uint8List _buffer;
  late Uint8List _thermalFrame;
  late Uint8List _imgFrame;

  /// 配置
  int _ROWS = 62;
  int _COLS = 80;

  /// 原始宽度
  int _width = 80;
  int _height = 62;

  late Map<String, dynamic> thermalInfo;
  late Image img;

  /// 构造函数
  // OpenCVProvider() {
  //   main();
  // }

  /// main 主流程
  Future<ui.Image> main() async {
    _buffer = hexStringToBuffer(mockHexString);

    var mainDataArr = parseMainData(_buffer);

    _thermalFrame = mainDataArr[0];
    _imgFrame = mainDataArr[1];

    thermalInfo = parseThermalFrame(_thermalFrame);

    // 温度矩阵
    var tempMatrix = buildTempMatrix(_imgFrame);

    // 降噪
    // var bilateralFilterMat =
    //     bilateralFilter(tempMatrix, _width, _height, 0, 0, 0);
    // print('888888888888888888888888888888888');
    // print(tempMatrix);
    // 归一化
    var grayMat = normalizeToGray(tempMatrix);

    // print('999999999999999999999999999999999');
    // print(grayMat);

    final img = await applyColorMapInferno(grayMat, _width, _height);

    return img;
  }

  /// 字符传转 buffer
  hexStringToBuffer(hexString) {
    // 移除空格并按每两个字符分割
    List<String> hexParts = hexString
        .replaceAll(' ', '')
        .splitMapJoin(
          RegExp(r'(.{2})'),
          onMatch: (m) => '${m.group(0)} ',
          onNonMatch: (n) => '',
        )
        .trim()
        .split(' ');

    // 转换为Uint8List
    Uint8List buffer = Uint8List(hexParts.length);
    for (int i = 0; i < hexParts.length; i++) {
      buffer[i] = int.parse(hexParts[i], radix: 16);
    }

    // 打印结果（以16进制格式）
    // print(buffer.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join(' '));

    return buffer;
  }

  //////////////////////////////////////////////////////////////////////////////
  /// 主数据解析
  /// 解析主数据并提取热成像帧和原始数据
  List<Uint8List> parseMainData(Uint8List bytes) {
    // 定义常量（需根据实际情况替换）
    const int thermalFrameOffset = 4 + 4 + 4 + 80 * 2;
    const int thermalFrameLength = 160;

    // 提取热成像帧数据
    final Uint8List thermalFrameRaw = bytes.sublist(
        thermalFrameOffset, thermalFrameOffset + thermalFrameLength);

    // 计算原始数据偏移量并提取
    final int imgRawDataOffset = thermalFrameOffset + thermalFrameLength;
    final int imgRawDataLength = _ROWS * _COLS * 2;
    final Uint8List imgRawData =
        bytes.sublist(imgRawDataOffset, imgRawDataOffset + imgRawDataLength);

    return [thermalFrameRaw, imgRawData];
  }

  //////////////////////////////////////////////////////////////////////////////
  /// 热成像帧数据解析器
  Map<String, dynamic> parseThermalFrame(Uint8List thermalFrameRaw) {
    final result = <String, dynamic>{};
    var offset = 0;

    // 读取指定字节数并解析为对应值
    int readBytes(int bytesSize) {
      // 提取指定字节范围
      final bytes = thermalFrameRaw.sublist(offset, offset + bytesSize);
      // print('offset: ${offset + 1}, view: $bytes');
      int value;

      // 根据字节大小解析不同类型数据
      if (bytesSize == 1) {
        // print('bytes: $bytes');
        // JavaScript中parseInt(bytes, 16)在Dart中对应将字节转换为整数
        value = bytes[0];
      } else if (bytesSize == 2) {
        final low = bytes[0];
        final high = bytes[1];
        // print('low: $low, high: $high');
        // 低字节在前，高字节在后的解析方式
        value = low + (high << 8);
      } else if (bytesSize == 4) {
        // 处理4字节数据（如时间戳）
        value =
            bytes[0] + (bytes[1] << 8) + (bytes[2] << 16) + (bytes[3] << 24);
      } else {
        throw ArgumentError('不支持的字节大小: $bytesSize');
      }

      // 移动偏移量
      offset += bytesSize;
      // print('offset: ${offset + 1}, value: $value');
      return value;
    }

    // ---------- 帧头信息解析 ----------
    result['frameCounter'] = readBytes(2);
    result['sensorVDD'] = readBytes(2) * 0.0001;
    result['sensorDieTemp'] = readBytes(2) * 0.01;
    result['timestamp'] = readBytes(4);
    result['maxPixel'] = readBytes(2) * 0.1;
    result['minPixel'] = readBytes(2) * 0.1;
    result['crc'] = readBytes(2);

    offset += 4; // 跳过预留的4字节

    // ---------- 推理信息解析 ----------
    result['rotateCoder'] = readBytes(1);
    result['personNum'] = readBytes(1);

    result['persons'] = [];
    // 使用clamp确保不超过最大人数限制
    final personCount = (result['personNum'] as int).clamp(0, 5);
    for (var i = 0; i < personCount; i++) {
      final person = {
        'score': readBytes(1),
        'x1': readBytes(1),
        'y1': readBytes(1),
        'x2': readBytes(1),
        'y2': readBytes(1),
        'distance': readBytes(1),
        'yAngle': readBytes(1),
        'xAngle': readBytes(1),
        'sportLevel': readBytes(1),
        'posture': readBytes(1),
      };
      result['persons'].add(person);
    }

    result['sleepStatus'] = readBytes(1);
    result['validZoneLeftAngle'] = readBytes(1);
    result['validZoneRightAngle'] = readBytes(1);
    result['validZoneFrontDistance'] = readBytes(1) * 0.1;
    result['validZoneBackDistance'] = readBytes(1) * 0.1;

    // ---------- 窗户信息解析 ----------
    result['windowNum'] = readBytes(1);
    result['windowsArr'] = [];
    for (var i = 0; i < 2; i++) {
      final windowInfo = {
        'x1': readBytes(1),
        'y1': readBytes(1),
        'x2': readBytes(1),
        'y2': readBytes(1),
        'yAngle': readBytes(1),
        'xAngle': readBytes(1),
        'temp': readBytes(2) * 0.1,
      };
      result['windowsArr'].add(windowInfo);
    }

    result['windowOpen'] = readBytes(1);

    // ---------- 热源信息解析 ----------
    result['hotSourceNum'] = readBytes(1);
    result['hotSources'] = [];
    for (var i = 0; i < 2; i++) {
      final hot = {
        'x1': readBytes(1),
        'y1': readBytes(1),
        'x2': readBytes(1),
        'y2': readBytes(1),
        'square': readBytes(1),
        'temp': readBytes(2) * 0.1,
      };
      result['hotSources'].add(hot);
    }

    result['hotSourceAbnormal'] = readBytes(1);

    // ---------- 房间温度信息解析 ----------
    result['floorTemp'] = readBytes(2) * 0.1;
    result['wallTemp'] = readBytes(2) * 0.1;
    result['ceilTemp'] = readBytes(2) * 0.1;
    result['averageTemp'] = readBytes(2) * 0.1;

    result['roomSquare'] = readBytes(1);
    result['distribution'] = readBytes(1);

    // ---------- 实时风口区域信息解析 ----------
    result['realtimeLeftAngle'] = readBytes(1);
    result['realtimeRightAngle'] = readBytes(1);
    result['realtimeFrontDistance'] = readBytes(1) * 0.1;
    result['realtimeBehindDistance'] = readBytes(1) * 0.1;

    // ---------- 保留字节解析 ----------
    final reserved = <int>[];
    for (var i = 0; i < 55; i++) {
      reserved.add(readBytes(1));
    }
    result['reserved'] = reserved;

    // print('解析帧数据=============================');
    // print(result);

    return result;
  }

  //////////////////////////////////////////////////////////////////////////////
  /// 构建温度矩阵
  /// 将原始字节数据转换为温度值矩阵（单位：开尔文）
  List<List<double>> buildTempMatrix(Uint8List rawBuf) {
    // 定义常量（需根据实际情况替换）
    final allData = <List<double>>[];

    for (var i = 0; i < _ROWS; i++) {
      final row = <double>[];

      for (var j = 0; j < _COLS; j++) {
        // 计算字节索引（每两个字节表示一个温度值）
        final idx = 2 * (i * _COLS + j);

        // 读取低字节和高字节
        final low = rawBuf[idx];
        final high = rawBuf[idx + 1];

        // 组合成uint16值（小端序）
        final valRaw = low + (high << 8);

        // 转换为开尔文温度
        final tempK = valRaw * 0.1;

        // 添加到当前行
        row.add(tempK);
      }

      // 添加当前行到矩阵
      allData.add(row);
    }

    return allData;
  }

//////////////////////////////////////////////////////////////////////////////
  /// 双边滤波器与归一化
  /// 双边滤波器 - 保留边缘的同时平滑图像
  ///
  /// 参数:
  /// - tempMatrix: 输入温度矩阵（单位：摄氏度）
  /// - width: 图像宽度
  /// - height: 图像高度
  /// - diameter: 滤波器直径（奇数）
  /// - sigmaColor: 颜色标准差，控制像素值差影响
  /// - sigmaSpace: 空间坐标标准差，控制邻域距离影响
  ///
  /// 返回: 滤波后的矩阵
  List<List<double>> bilateralFilter(List<List<double>> tempMatrix, int width,
      int height, int diameter, double sigmaColor, double sigmaSpace) {
    // 高斯函数
    double gaussian(double x, double sigma) {
      return exp(-(x * x) / (2 * sigma * sigma));
    }

    // 创建结果矩阵并初始化为0
    final filtered = List.generate(
      height,
      (_) => List<double>.filled(width, 0.0),
    );

    // 计算半径
    final radius = (diameter / 2).floor();

    // 遍历每个像素
    for (var y = 0; y < height; y++) {
      for (var x = 0; x < width; x++) {
        double sumWeight = 0.0;
        double weightedSum = 0.0;

        // 遍历邻域
        for (var ky = -radius; ky <= radius; ky++) {
          for (var kx = -radius; kx <= radius; kx++) {
            final ny = y + ky;
            final nx = x + kx;

            // 检查是否在图像范围内
            if (ny >= 0 && ny < height && nx >= 0 && nx < width) {
              // 计算空间权重（基于距离）
              final spatialWeight =
                  gaussian(sqrt(kx * kx + ky * ky), sigmaSpace);

              // 计算颜色权重（基于温度差异）
              final colorWeight = gaussian(
                  (tempMatrix[ny][nx] - tempMatrix[y][x]).abs(), sigmaColor);

              // 总权重
              final totalWeight = spatialWeight * colorWeight;

              sumWeight += totalWeight;
              weightedSum += totalWeight * tempMatrix[ny][nx];
            }
          }
        }

        // 归一化结果
        filtered[y][x] =
            sumWeight > 0 ? weightedSum / sumWeight : tempMatrix[y][x];
      }
    }

    return filtered;
  }

  //////////////////////////////////////////////////////////////////////////////
  // 归一化到灰度
  List<List<double>> normalizeToGray(List<List<num>> filtered) {
    // 获取数组的最大值和最小值
    var result = getMaxMin(filtered);
    num? maxVal = result[0];
    num? minVal = result[1];

    // 处理边界情况
    if (maxVal == null || minVal == null || maxVal == minVal) {
      return List.generate(
          filtered.length, (_) => List.filled(filtered[0].length, 0.0));
    }

    // 执行归一化映射
    return filtered.map((row) {
      return row.map((item) {
        return ((item - minVal) * 255 / (maxVal - minVal))
            .clamp(0.0, 255.0)
            .toDouble();
      }).toList();
    }).toList();
  }

  // 获取矩阵的最大最小值
  List<num?> getMaxMin(List<List<dynamic>> arr) {
    // 检查是否为有效二维数组
    if (arr.isEmpty) {
      return [null, null];
    }

    // 初始化最大值和最小值
    num maxVal = double.negativeInfinity;
    num minVal = double.infinity;

    // 遍历二维数组
    for (var i = 0; i < arr.length; i++) {
      // 跳过非数组元素
      if (arr[i] is! List) continue;

      for (var j = 0; j < arr[i].length; j++) {
        // 尝试将元素转换为数字
        num? current;
        if (arr[i][j] is num) {
          current = arr[i][j] as num;
        } else if (arr[i][j] is String) {
          current = num.tryParse(arr[i][j] as String);
        }

        // 跳过非数字元素
        if (current == null) continue;

        // 更新最大值和最小值
        if (current > maxVal) maxVal = current;
        if (current < minVal) minVal = current;
      }
    }

    // 如果没有找到有效数字
    if (maxVal == double.negativeInfinity && minVal == double.infinity) {
      return [null, null];
    }

    return [maxVal, minVal];
  }

  //////////////////////////////////////////////////////////////////////////////
  // 将温度值映射到Inferno颜色空间
  Color temperatureToColor(double value) {
    // print('temperatureToColor value ${value}');

    // 确保索引在COLOR_CONFIG范围内
    final index = int.parse(value.toStringAsFixed(0));
    // print('temperatureToColor index ${index}');
    final r = COLOR_CONFIG[index][2];
    final g = COLOR_CONFIG[index][1];
    final b = COLOR_CONFIG[index][0];

    return Color.fromARGB(255, r, g, b);
  }


  // 功能：将灰度图映射到Inferno伪彩色
  Future<ui.Image> applyColorMapInferno(
      List<List<double>> grayMat, int width, int height) async {
    // 展平灰度矩阵
    final flattened = grayMat.expand((row) => row).toList();
    // print('99999999999999999999999999');
    // print(flattened);
    // 创建一个用于存储颜色的图像
    final imageData = List<int>.filled(width * height * 4, 0);

    flattened.asMap().forEach((i, value) {
      final color = temperatureToColor(value);
      final index = i * 4;
      imageData[index + 0] = color.red; // R
      imageData[index + 1] = color.green; // G
      imageData[index + 2] = color.blue; // B
      imageData[index + 3] = 255; // A
    });
    
    final completer = Completer<ui.Image>();

    // 创建Image对象
    ui.decodeImageFromPixels(
      Uint8List.fromList(imageData),
      _width,
      _height,
      ui.PixelFormat.rgba8888,
      (ui.Image img) => completer.complete(img), 
    );

    final image = await completer.future;
    return image;
  }

  ////////////////////////////////////////////////////////////////
  // 获取放大系数
  getAmplificationCoefficient(screenWidth){
    double num = screenWidth / _width;
    return num;
  }
}
